﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Principal;
using System.Text;
using Microsoft.Win32.SafeHandles;

namespace QT.Windows
{
    /// <summary>
    /// 用户登陆方法组
    /// </summary>
    public class WinLogon
    {
        #region Attributes

        private const int LOGON32_PROVIDER_DEFAULT = 0;
        private const int LOGON32_LOGON_INTERACTIVE = 2;

        #endregion

        #region DllImport

        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
            int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private extern static bool CloseHandle(SafeTokenHandle handle);
        
        [DllImport("Advapi32.DLL")]
        private static extern bool RevertToSelf();

        #endregion

        #region Method

        /// <summary>
        /// 使用模拟用户登陆
        /// </summary>
        /// <param name="uID">用户名</param>
        /// <param name="Pass">密码</param>
        /// <param name="phToken">令牌环（返回值）</param>
        /// <returns>SafeTokenHandle</returns>
        public static bool Logon(string uID, string Pass, out SafeTokenHandle phToken)
        {
            bool rValue = LogonUser(uID, "", Pass, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out phToken);
            return rValue;
        }

        /// <summary>
        /// 注销模拟登陆的用户
        /// </summary>
        /// <param name="phToken">令牌环</param>
        /// <returns>bool</returns>
        public static bool Logout(SafeTokenHandle phToken)
        {
            return CloseHandle(phToken);
        }

        /// <summary>
        /// 返回当前系统用户
        /// </summary>
        /// <returns>bool</returns>
        public static bool LogSelf()
        {
            return RevertToSelf();
        }

        /// <summary>
        /// 验证当前用户是否管理员组
        /// </summary>
        /// <returns></returns>
        public static bool IsAdministrators()
        {
            WindowsIdentity identity = WindowsIdentity.GetCurrent();
            WindowsPrincipal principal = new WindowsPrincipal(identity);
            return principal.IsInRole(WindowsBuiltInRole.Administrator);
            //for (int i = 0; i < identity.Groups.Count; i++)
            //{
            //    if (identity.Groups[i].Value.Contains("S-1-5-32-544")) return true;                     
            //}

            //return false;
        }

        /// <summary>
        /// 以指定用户运行指定的程序
        /// </summary>
        /// <param name="User">用户名</param>
        /// <param name="Pass">密码</param>
        /// <param name="WorkDir">目标程序的工作目录</param>
        /// <param name="AppName">目标程序文件。必须为包含目录和文件名的完整路径</param>
        /// <param name="Id">参数</param>
        public static void CreateProcess(string User,string Pass,string WorkDir,string AppName,string Id)
        {
            //使用管理员身份重新运行程序
            Process process = new Process();
            process.StartInfo.UserName = User;
            string strPwd = Pass;
            SecureString password = new SecureString();
            foreach (char c in strPwd.ToCharArray())
            {
                password.AppendChar(c);
            }
            process.StartInfo.Password = password;
            process.StartInfo.Domain = ".";
            process.StartInfo.WorkingDirectory = WorkDir;
            process.StartInfo.FileName = AppName;
            process.StartInfo.Arguments = Id;
            process.StartInfo.UseShellExecute = false;
            process.Start();
        }

        #endregion

    }

    /// <summary>
    /// 令牌环变量
    /// </summary>
    public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
    {
        private SafeTokenHandle()
            : base(true)
        {
        }

        [DllImport("kernel32.dll")]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [SuppressUnmanagedCodeSecurity]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool CloseHandle(IntPtr handle);

        /// <summary>
        /// 释放令牌
        /// </summary>
        /// <returns></returns>
        protected override bool ReleaseHandle()
        {
            return CloseHandle(handle);
        }                      
    }
}
